package br.com.dataphonebr.util;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;
import br.com.dataphonebr.adapter.AdministratorListAdapter;
import br.com.dataphonebr.entity.Atividade;
import br.com.dataphonebr.enumerator.StatusAtividade;
import br.com.dataphonebr.schedule.SampleAlarmReceiver;
import br.com.dataphonebr.service.AtividadeService;

@SuppressLint("UseSparseArrays") public class AlarmUtil {
	
	public enum Lists{
		TODAY_LIST("today_list_dph"),
		SENT_LIST("sent_list_dph");
		
		private String name;
		
		private Lists(String name) {
			this.name = name;
		}
		
		public String getName() {
			return name;
		}
	}

	public final static Long ID_UPDATE = -1L;
	private Util util = new Util();
	private Context context;
	private SampleAlarmReceiver receiver = new SampleAlarmReceiver();
	
	public AlarmUtil(Context context) {
		this.context = context;
	}
	
	private void saveTodayList(Set<String> todayList){
		this.createList(Lists.TODAY_LIST, todayList);
	}

	private void saveSentList(Set<String> sentList){
		this.createList(Lists.SENT_LIST, sentList);
	}
	
	private void createList(Lists nameList, Set<String> list){
		SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
		Editor editor = sharedpreferences.edit();
		editor.putStringSet(nameList.getName(), list);
		editor.commit();
	}
	
	private List<String> getListToRemove(Long id){
		Set<String> todayList = this.getTodaySet();
		List<String> listToRemove = new ArrayList<String>();
		if (todayList != null && !todayList.isEmpty()){
			for (String time : todayList){
				if (time != null){
					String theTime[] = time.split(AlarmVO.TODAY_LIST_SEPARATOR);
					Long idList = Long.parseLong(theTime[0]);
					if (idList != null && idList.equals(id)){
						listToRemove.add(time);
					}
				}
			}
		}
		return listToRemove;
	}
	
	public void addAlarmToManager(Atividade atividade){
		if (atividade != null && atividade.getCodigo() != null && atividade.getStatus().equals(StatusAtividade.EM_ABERTO)){
			mergeTodayList(atividade);
			receiver.addAlarm(getAlarms(), context);
		}
	}

	public void mergeTodayList(Atividade atividade){
		List<AlarmVO> newAlarms = this.createNewAlarmsVO(atividade);
		List<AlarmVO> currentAlarms = this.getAlarms();
		if (currentAlarms == null)
			currentAlarms = new ArrayList<AlarmVO>();
		if (newAlarms != null && !newAlarms.isEmpty()){
			currentAlarms.addAll(newAlarms);
		}
		mergeRequestCode(currentAlarms);
		createNewTodayList(currentAlarms);
	}
	
	private void createNewTodayList(List<AlarmVO> currentAlarms){
		Set<String> newTodayList = new HashSet<String>();
		if (currentAlarms != null && !currentAlarms.isEmpty()){
			for (AlarmVO mAlarm : currentAlarms){
				if (mAlarm != null && mAlarm.isValid()){
					newTodayList.add(mAlarm.stringAlarm());
				}
			}
		}
		saveTodayList(newTodayList);
	}
	
	private List<Date> getUpdateTimes(){
		List<Date> times = new ArrayList<Date>();
		int initialHour = 23;
		for (int i = 0; i<=3;i++){
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(new Date());
			calendar.set(Calendar.HOUR, initialHour);
			calendar.set(Calendar.MINUTE, 59);
			calendar.set(Calendar.SECOND, 50);
			times.add(calendar.getTime());
			initialHour = initialHour+6;
		}
		return times;
	}

//	private List<Date> getUpdateTimesTeste(){
//		List<Date> times = new ArrayList<Date>();
//		for (int i = 0; i<=3;i++){
//			Calendar calendar = Calendar.getInstance();
//			calendar.setTime(new Date());
//			calendar.set(Calendar.HOUR, calendar.get(Calendar.HOUR));
//			calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE)+i+1);
//			calendar.set(Calendar.SECOND, 0);
//			times.add(calendar.getTime());
//		}
//		return times;
//	}
	
	private void mergeRequestCode(List<AlarmVO> alarms){
		if (alarms != null && !alarms.isEmpty()){
			int i = 0;
			for (Date date : getUpdateTimes()){
				AlarmVO alarm = createNewAlarmVO(ID_UPDATE, date);
				alarms.add(i, alarm);
				i++;
			}
			int newRequestCode = 0;
			for (AlarmVO alarm : alarms){
				alarm.setRequestCode(newRequestCode);
				newRequestCode++;
			}
		}
	}
	
	private List<AlarmVO> createNewAlarmsVO(Atividade atividade){
		if (atividade != null && atividade.getCodigo() != null){
			List<AlarmVO> newAlarms = new ArrayList<AlarmVO>();
			AlarmVO alarm = createNewAlarmVO(atividade.getCodigo(), atividade.getHoraAviso());
			if (alarm != null){
				newAlarms.add(alarm);
			}
			if (atividade.getHoraIni() != null) {
				String alarm1 = util.timeToString(atividade.getHoraIni());
				String alarm2 = util.timeToString(atividade.getHoraAviso());
				if (!alarm1.equals(alarm2)){
					alarm = createNewAlarmVO(atividade.getCodigo(), atividade.getHoraIni());
					if (alarm != null){
						newAlarms.add(alarm);
					}
				}
			}
			return newAlarms;
		}
		return null;
	}
	
	private AlarmVO createNewAlarmVO(Long id, Date initialTime){
		if (id != null && initialTime != null){
			AlarmVO alarm = new AlarmVO();
			alarm.setId(id);
			alarm.setTime(util.addDateAndTime(new Date(), initialTime));
			return alarm;
		}
		return null;
	}
	
	public List<AlarmVO> getAlarmsSent(){
		return this.getAlarmsFromList(this.getSentList());
	}
	
	private List<AlarmVO> getAlarmsFromList(List<String> list){
		final int ID_INDEX = 0;
		final int TIME_INDEX = 1;
		final int REQUEST_CODE_INDEX = 2;
		List<AlarmVO> myAlarms = new ArrayList<AlarmVO>();
		List<String> todayListOfficial = new ArrayList<String>(list);
		if (todayListOfficial != null && !todayListOfficial.isEmpty()){
			for (String time : todayListOfficial){
				if (time != null && !time.isEmpty()){
					String alarm[] = time.split(AlarmVO.TODAY_LIST_SEPARATOR);
					Long idList = Long.parseLong(alarm[ID_INDEX]);
					int requestCode = 0;
					if (alarm[REQUEST_CODE_INDEX] != null){
						try {
							requestCode = Integer.parseInt(alarm[REQUEST_CODE_INDEX]);
						} catch (Exception e){
							e.printStackTrace();
						}
					}
					
					AlarmVO myAlarm = new AlarmVO();
					myAlarm.setId(idList);
					myAlarm.setRequestCode(requestCode);
					myAlarm.setTime(createCalendarToAlarm(alarm[TIME_INDEX]));
					myAlarms.add(myAlarm);
				}
			}
		}
		return myAlarms;
	}

//	TODO: Alterar
	public List<AlarmVO> getAlarms(){
		final int ID_INDEX = 0;
		final int TIME_INDEX = 1;
		final int REQUEST_CODE_INDEX = 2;
		List<AlarmVO> myAlarms = new ArrayList<AlarmVO>();
		List<String> todayListOfficial = new ArrayList<String>(this.getTodayList());
		if (todayListOfficial != null && !todayListOfficial.isEmpty()){
			for (String time : todayListOfficial){
				if (time != null && !time.isEmpty()){
					String alarm[] = time.split(AlarmVO.TODAY_LIST_SEPARATOR);
					Long idList = Long.parseLong(alarm[ID_INDEX]);
					int requestCode = 0;
					if (alarm[REQUEST_CODE_INDEX] != null){
						try {
							requestCode = Integer.parseInt(alarm[REQUEST_CODE_INDEX]);
						} catch (Exception e){
							e.printStackTrace();
						}
					}
					
					AlarmVO myAlarm = new AlarmVO();
					myAlarm.setId(idList);
					myAlarm.setRequestCode(requestCode);
					myAlarm.setTime(createCalendarToAlarm(alarm[TIME_INDEX]));
					myAlarms.add(myAlarm);
				}
			}
		}
		return myAlarms;
	}

	
	private Date createCalendarToAlarm(String justTime){
		final int HOUR_INDEX = 0;
		final int MINUTE_INDEX = 1;
		String time[] = justTime.split(":");
		int hour = Integer.parseInt(time[HOUR_INDEX]);
		int minutes = Integer.parseInt(time[MINUTE_INDEX]);
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(new Date());
    	calendar.setTimeInMillis(System.currentTimeMillis());
    	calendar.set(Calendar.HOUR_OF_DAY, hour);
    	calendar.set(Calendar.MINUTE, minutes);
    	calendar.set(Calendar.SECOND, 0);
    	return calendar.getTime();
	}
	
	public void updateAlarmToManager(Atividade atividade){
		if (atividade != null && atividade.getCodigo() != null){
			removeAlarmFromTodayList(atividade.getCodigo());
			removeAlarmFromTodayList(ID_UPDATE);
			receiver.removeAlarm(getAlarmsByCodigo(atividade.getCodigo()), context);
			receiver.removeAlarm(getAlarmsByCodigo(ID_UPDATE), context);
			addAlarmToManager(atividade);
		}
	}
	
	public void removeAlarmFromManager(Long id){
		if (id != null && id > 0){
			removeAlarmFromTodayList(id);
			removeAlarmFromTodayList(ID_UPDATE);
			mergeTodayList(null);
			receiver.removeAlarm(getAlarmsByCodigo(id), context);
			receiver.removeAlarm(getAlarmsByCodigo(ID_UPDATE), context);
		}
	}
	
	private void removeAlarmFromTodayList(Long id){
		List<String> listToRemove = this.getListToRemove(id);
		if (listToRemove != null && !listToRemove.isEmpty()){
			Set<String> todayList = this.getTodaySet();
			for (String timeToRemove : listToRemove){
				todayList.remove(timeToRemove);
			}
			saveTodayList(todayList);
		}
	}
	
	public void addTodayListToAlarm(List<Atividade> atividades){
		List<AlarmVO> newAlarms = new ArrayList<AlarmVO>();
		if (atividades != null && !atividades.isEmpty()){
			for (Atividade atividade : atividades){
				if (atividade.getStatus().equals(StatusAtividade.EM_ABERTO)){
					newAlarms.addAll(createNewAlarmsVO(atividade));
				}
			}
		}
		mergeRequestCode(newAlarms);
		createNewTodayList(newAlarms);
	}
	
	public void cleanSentList(){
		saveSentList(new HashSet<String>());
	}
	
	public void addToSentList(List<AlarmVO> alarms){
		if (alarms != null && !alarms.isEmpty()){
			Set<String> sentList = this.getSentSet();
			if (sentList == null || sentList.isEmpty()){
				sentList = new HashSet<String>();
				for (AlarmVO newAlarm : alarms){
					if (newAlarm != null && newAlarm.getId() != null){
						sentList.add(newAlarm.stringAlarm());
					}
				}				
			} else {
				List<AlarmVO> alarmsAux = getAlarmsSent();
				for (AlarmVO newAlarm : alarms){
					boolean existeAlarme = false;
					for (AlarmVO alarmSent : alarmsAux){
						if (alarmSent.getId() != null && newAlarm.getId() != null && alarmSent.getId().equals(newAlarm.getId())){
							existeAlarme = true;
						}
					}
					if (!existeAlarme)
						sentList.add(newAlarm.stringAlarm());
				}
			}
			saveSentList(sentList);
		}
	}
	
	public List<String> getTodayList(){
		return new ArrayList<String>(this.getTodaySet());
	}

	public List<String> getSentList(){
		return new ArrayList<String>(this.getSentSet());
	}

	public Set<String> getTodaySet(){
		return this.getListDph(Lists.TODAY_LIST);
	}
	
	public Set<String> getSentSet(){
		return this.getListDph(Lists.SENT_LIST);
	}
	
	private Set<String> getListDph(Lists list){
		SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
		Set<String> mList = sharedpreferences.getStringSet(list.name, new HashSet<String>());
		return mList;
	}
  
	public AlarmVO getAlarmByRequestCode(int requestCode){
		List<AlarmVO> alarms = this.getAlarms();
		if (alarms != null && !alarms.isEmpty()){
			for (AlarmVO alarm : alarms){
				if (alarm.getRequestCode().intValue() == requestCode){
					return alarm;
				}
			}
		}
		return new AlarmVO();
	}

	public List<AlarmVO> getAlarmsByCodigo(Long codigo){
		List<AlarmVO> alarmsToReturn = new ArrayList<AlarmVO>();
		List<AlarmVO> alarms = this.getAlarms();
		if (alarms != null && !alarms.isEmpty()){
			for (AlarmVO alarm : alarms){
				if (alarm.getId() == codigo){
					alarmsToReturn.add(alarm);
				}
			}
		}
		return alarmsToReturn;
	}
	
	public boolean isTimeValidToAlarm(Date date){
		if (date != null){
			Date now = new Date();
			return util.time1IsHigherThanTime2(date, now);
//			Calendar calendarAlarmTime = Calendar.getInstance();
//			calendarAlarmTime.setTime(date);
//			Calendar calendarNow = Calendar.getInstance();
//			calendarNow.setTime(now);
//			if (calendarAlarmTime.get(Calendar.HOUR_OF_DAY) > calendarNow.get(Calendar.HOUR_OF_DAY)){
//				return true;
//			}
//			if (calendarAlarmTime.get(Calendar.HOUR_OF_DAY) == calendarNow.get(Calendar.HOUR_OF_DAY) && calendarAlarmTime.get(Calendar.MINUTE) >= calendarNow.get(Calendar.MINUTE)){
//				return true;
//			}
		}
		return false;
	}

    public boolean isValidAlarm (AlarmVO alarm){
    	if (alarm != null && alarm.getTime() != null){
    		Date now = new Date();
    		Calendar calendarAlarmTime = Calendar.getInstance();
    		calendarAlarmTime.setTime(alarm.getTime());
    		Calendar calendarNow = Calendar.getInstance();
    		calendarNow.setTime(now);
    		if (calendarAlarmTime.get(Calendar.HOUR_OF_DAY) > calendarNow.get(Calendar.HOUR_OF_DAY)){
    			return true;
    		}
    		if (calendarAlarmTime.get(Calendar.HOUR_OF_DAY) == calendarNow.get(Calendar.HOUR_OF_DAY) && calendarAlarmTime.get(Calendar.MINUTE) > calendarNow.get(Calendar.MINUTE)){
    			return true;
    		}
    	}
   		return false;
    }
    
    public void updateAlarm(){
    	SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
		boolean alarmPrefs = preferences.getBoolean("pref_ativar_alarme", false);
		SampleAlarmReceiver alarm = new SampleAlarmReceiver();
		if (alarmPrefs){
			alarm.cancelAlarm(context);
			addTodayListToAlarm(getAtividadesParaHoje());
			alarm.setAlarm(context);
		} else {
			alarm.cancelAlarm(context);
		}
    }

	public List<Atividade> getAtividadesParaHoje(){
		AtividadeService atividadeService = new AtividadeService(context);
		AdministratorListAdapter adapter = new AdministratorListAdapter(context);
		adapter.setLista(atividadeService.selectAtividadesNotificaveis());
		adapter.processarAtividadesParaHoje();
		return adapter.getAtividadesParaHoje();
	}
	
	private List<Atividade> getAtividadesFromAlarmVO(List<AlarmVO> alarms){
		List<Atividade> atividades = new ArrayList<Atividade>();
		if (alarms != null && !alarms.isEmpty()){
			AtividadeService atividadeService = new AtividadeService(context);
			for (AlarmVO alarm : alarms){
				Atividade atividade = atividadeService.selectById(alarm.getId());
				if (atividade != null && atividade.getCodigo() != null){
					atividades.add(atividade);
				}
			}
		}
		return atividades;
	}	
	
	public List<Atividade> getAtividadesNotificadas(){
		return this.getAtividadesFromAlarmVO(this.getAlarmsSent());
	}


//	public Map<Long, Calendar> getAlarm(){
//		final int ID_INDEX = 0;
//		final int TIME_INDEX = 1;
//		Map<Long, Calendar> myAlarms = new HashMap<Long, Calendar>();
//		List<String> todayListOfficial = new ArrayList<String>(this.getTodayList());
//		if (todayListOfficial != null && !todayListOfficial.isEmpty()){
//			for (String time : todayListOfficial){
//				if (time != null && !time.isEmpty()){
//					String alarm[] = time.split(TODAY_LIST_SEPARATOR);
//					Long idList = Long.parseLong(alarm[ID_INDEX]);
//					myAlarms.put(idList, createCalendarToAlarm(alarm[TIME_INDEX]));
//				}
//			}
//		}
//		return myAlarms;
//	}
}
